Release 10.1A: OpenEdge Development:
Progress 4GL Handbook


Avoiding stale handles

You saw the errors that you get if you inadvertently try to reference (or dereference, as the error message says) a stale handle. A stale handle is one that holds a pointer to an object that no longer exists. If you make sure that your objects always live just as long as they should, then you shouldn’t get this type of error. But it’s still very good practice to check the validity of a handle when there’s any chance that it might be invalid, which almost certainly includes whenever it comes from another procedure that might be maintained independently of the one that needs to use the handle.

You can use the VALID-HANDLE function to check whether a handle is valid. If you do use this check, then always determine how your procedure should react if a handle that ought to be valid turns out not to be. Simply substituting your own “Invalid handle!” message for the default one that Progress gives you is not the right approach. There are many things you can try to blame the end user of your application for, but supplying a procedure with an invalid object handle is not one of them.

Remember, too, that once you have encountered an invalid handle, whether it is a stale handle for a deleted object or simply a handle variable that was never properly initialized, your end user will get another ugly message for every statement in your procedure that vainly tries to reference it. In the Runmake.p example, the procedure generated three internal system errors because the buffer handle was not valid. It could easily have been a hundred errors, if the procedure had gone on to continue to try to work with that invalid handle. Never risk subjecting your end users to this abuse.

The VALID-HANDLE function is also very useful and necessary anytime your code is walking through a chain of handles, such as in this procedure that displays all the windows currently running in the session:

DEFINE VARIABLE hChild AS HANDLE     NO-UNDO. 
hChild = SESSION:FIRST-CHILD. 
REPEAT WHILE VALID-HANDLE(hChild): 
   DISPLAY hChild:NAME FORMAT "X(30)" 
       hChild:TYPE WITH FRAME F 10 DOWN. 
    hChild = hChild:NEXT-SIBLING. 
END. 

You could also use the VALID-HANDLE function as a signal that tells your procedure whether an attempt to locate a particular object was successful or not, somewhat like the AVAILABLE function after a FIND statement on a buffer.

In early versions of Progress, it was possible (and quite likely) that if you deleted an object and then created another object, even an object of a different type, the new object would have the same handle value as the object you just deleted. Therefore, the VALID-HANDLE function could return true because the handle was pointing to a valid object, even though it was not the object you expected it to be. The TYPE and UNIQUE-ID object attributes exist largely to help you identify whether an object is the same one you referred to earlier. As of Progress Version 9.1C, this is no longer the case. Handles are allocated in such a way that you cannot have a handle variable that inadvertently points to a different object residing in the same memory location as one that was deleted earlier in the session. Therefore, you can be confident that when you use the VALID-HANDLE function, it is not only telling whether the object the handle points to is some valid object, but assuring you that it is the same object it always was before. Progress does this using a mechanism called opaque handles. You do not need to do anything special to get the benefit of them.


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095